using System;
using System.IO;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Text;
using System.Text.RegularExpressions;
using System.Diagnostics;

using My.IdlConverter.Core;
using My.IdlConverter.Core.Util;
using My.IdlConverter.Core.Output;
using My.IdlConverter.Core.Filters;
using My.IdlConverter.Core.Graphics;

namespace My.IdlConverter.Com
{
    public class ComRegistarExport : ExportBase
    {
        private static readonly string RegistryExp = "IDR.*REGISTRY.*";
        private static readonly string IDRExp = @"\#define.*IDR.*";

        private StringCollection _IDRCache = new StringCollection();

        public ComRegistarExport(string targetPath)
            :base(targetPath)
        {
        }

        public override void Export()
        {
            IList<ClassTree> allFinalClasses = ClassForest.Instance.ChildTrees;
            Class refClass = null;
            StringBuilder rcRegistries = new StringBuilder();
            rcRegistries.Append(GetOneRegsitry(Component.Name));

            ExportEventArgs args = new ExportEventArgs();
            foreach (ClassTree nextTree in allFinalClasses)
            {
                refClass = nextTree.ReferObj as Class;
                Debug.Assert(refClass != null);
                string fileName = ClassModifier.GetTitle(refClass) + ".rgs";
                string pathName = Path.Combine(TargetPath, fileName);
                RegisterClassResource(pathName,refClass, ref rcRegistries);
                args.FileName = pathName;
                FireExportEvent(args);
            }

            ModifyLibraryResourceFile(rcRegistries);
        }

        private void RegisterClassResource(string pathName,Class theClass, ref StringBuilder rcRegistries)
        {
            IStreamWriter<string> writer = new TextStreamWriter<string>(pathName);
            writer.Write(ComRegistarTemplate.Instantiate(ComGuidCenter.Apply(theClass.Name).ToString(),ClassModifier.GetTitle(theClass)));
            rcRegistries.Append(GetOneRegsitry(ClassModifier.GetTitle(theClass)));
        }

        private void ModifyLibraryResourceFile(StringBuilder rcRegistries)
        {
            string rcPathName = Path.Combine(TargetPath,Component.Name+".rc");
            //Debug.Assert(File.Exists(rcPathName));
            string content = "";
            if (My.IdlConverter.Core.Util.IOHelper.ReadToEnd(rcPathName, out content))
            {
                MatchCollection matchCol = Regex.Matches(content, RegistryExp);
                int i = 1;
                int count = matchCol.Count;
                if (count > 0)
                {
                    foreach (Match nextMatch in matchCol)
                    {
                        int pos = content.IndexOf(nextMatch.Value);
                        if (pos != -1)
                        {
                            content = content.Remove(pos, nextMatch.Value.Length);
                        }
                        i++;
                        if (i == count)
                        {
                            content = content.Insert(pos,rcRegistries.ToString());
                        }
                    }
                }
            }
            else
            {
                content += rcRegistries.ToString();
            }
            IStreamWriter<string> writer = new TextStreamWriter<string>(rcPathName);
            writer.Write(content);

            ModifyResourceHeaderFile(Path.Combine(TargetPath,"resource.h"));
        }

        private string GetOneRegsitry(string registryName)
        {
            string IDR = "IDR_" + StringUtil.UpperString(registryName);
            _IDRCache.Add(IDR);
            return String.Format("{0}\t\t\t\tREGISTRY\t\t\t\t\"{1}.rgs\"{2}", IDR, registryName, Environment.NewLine);
        }

        private void ModifyResourceHeaderFile(string filePathName)
        {
            string content = "";
            if (IOHelper.ReadToEnd(filePathName,out content))
            {
                MatchCollection matchCol = Regex.Matches(content,IDRExp);
                if (matchCol.Count > 10)
                    return;
                Match lastMatch = matchCol[matchCol.Count-1];
                int pos = content.LastIndexOf(lastMatch.Value);
                Debug.Assert(pos != -1);
                pos += lastMatch.Value.Length;

                StringBuilder IDRs = new StringBuilder();
                int index = 300;
                IDRs.AppendLine();
                foreach (string nextIDR in _IDRCache)
                {
                    IDRs.AppendLine(String.Format("#define {0}\t\t{1}",nextIDR,index++));
                }
                content = content.Insert(pos,IDRs.ToString());

                IStreamWriter<string> writer = new TextStreamWriter<string>(filePathName);
                writer.Write(content);
            }
        }
    }
}
